package server

import (
	"shop-manager/internal/do"
	"shop-manager/internal/repos/supermarket"
	"shop-manager/internal/server/router"
	"shop-manager/internal/vo"

	"github.com/gin-gonic/gin"
)

type RspModel struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
	Data any    `json:"data"`
}

func (s *Server) Route() error {
	r := s.engine
	api := r.Group("/api")

	// 商品分类元信息管理
	router.RegisterCategoryMeta(api, s.categoryRepo, handleBizRsp, handleBizListRsp)
	// 商品分类管理
	router.RegisterCategory(api, s.categoryRepo, s.categoryLogic, handleBizRsp, handleBizListRsp)
	// 商品管理
	router.RegisterGoods(api, s.goodsRepo, s.goodsLogic, handleBizRsp, handleBizListRsp)
	// 厂家返点管理
	router.RegisterFactoryRebate(api, s.factoryRebateRepo, s.factoryRebateLogic, handleBizRsp, handleBizListRsp)

	// 合同管理
	router.RegisterContract(api, s.contractLogic, handleBizRsp, handleBizListRsp)

	// 超市基本信息
	supermarketApiGroup := api.Group("/supermarket")
	{
		supermarketApiGroup.POST("/create", func(ctx *gin.Context) {
			type ReqJson struct {
				Name    string
				Contact string
			}
			var req ReqJson
			if err := ctx.BindJSON(&req); err != nil {
				return
			}
			id, err := s.supermarketRepo.Create(ctx, &do.Supermarket{
				Name:    req.Name,
				Contact: req.Contact,
			})
			handleBizRsp(ctx, id, err)
		})
		// update
		supermarketApiGroup.POST("/update", func(ctx *gin.Context) {
			type ReqJson struct {
				ID      int
				Name    string
				Contact string
				Status  int
			}
			var req ReqJson
			if err := ctx.BindJSON(&req); err != nil {
				return
			}
			err := s.supermarketRepo.Update(ctx, &do.Supermarket{
				ID:      req.ID,
				Name:    req.Name,
				Contact: req.Contact,
				Status:  req.Status,
			})
			handleBizRsp(ctx, nil, err)
		})
		// list
		supermarketApiGroup.POST("/list", func(ctx *gin.Context) {
			type ReqJson struct {
				Status   int
				Page     int
				PageSize int
				Search   string
				Sorts    string
			}
			var req ReqJson
			if err := ctx.BindJSON(&req); err != nil {
				return
			}
			ss, total, err := s.supermarketRepo.List(ctx, supermarket.ListParam{
				Status:   req.Status,
				Page:     req.Page,
				PageSize: req.PageSize,
				Search:   req.Search,
				Sorts:    req.Sorts,
			})
			handleBizListRsp(ctx, ss, total, err)
		})
	}

	// 促销员
	salesPersonApiGroup := api.Group("/salesperson")
	{
		salesPersonApiGroup.POST("/create", func(ctx *gin.Context) {
			type ReqJson = vo.CreateSalesPersonReq
			var req ReqJson
			if err := ctx.BindJSON(&req); err != nil {
				return
			}

			logicRsp, err := s.salesPersonLogic.CreateSalesPerson(ctx, req)
			handleBizRsp(ctx, logicRsp, err)
		})
		// update
		salesPersonApiGroup.POST("/update", func(ctx *gin.Context) {
			var req vo.UpdateSalesPersonReq
			if err := ctx.BindJSON(&req); err != nil {
				return
			}
			err := s.salesPersonRepo.Update(ctx, &do.SalesPerson{
				ID:            req.ID,
				Name:          req.Name,
				Note:          req.Note,
				SupermarketID: req.SupermarketID,
				BasicSalary:   req.BasicSalary,
			})
			handleBizRsp(ctx, nil, err)
		})
		// list
		salesPersonApiGroup.POST("/list", func(ctx *gin.Context) {
			type ReqJson = vo.ListSalesPersonReq
			var req ReqJson
			if err := ctx.BindJSON(&req); err != nil {
				return
			}
			logicRsp, err := s.salesPersonLogic.ListSalesPerson(ctx, req)
			handleBizVoRsp(ctx, logicRsp, err)
		})
	}

	// 通用 人员管理接口
	personApiGroup := api.Group("/person")
	{
		personApiGroup.POST("/create", func(ctx *gin.Context) {
			type ReqJson = vo.CreatePersonReq
			var req ReqJson
			if err := ctx.BindJSON(&req); err != nil {
				return
			}

			logicRsp, err := s.personLogic.CreatePerson(ctx, req)
			handleBizRsp(ctx, logicRsp, err)
		})
		// update
		personApiGroup.POST("/update", func(ctx *gin.Context) {
			var req vo.UpdatePersonReq
			if err := ctx.BindJSON(&req); err != nil {
				return
			}
			err := s.personRepo.Update(ctx, &do.Person{
				ID:   req.ID,
				Name: req.Name,
				Note: req.Note,
				Type: req.Type,
			})
			handleBizRsp(ctx, nil, err)
		})
		// list
		personApiGroup.POST("/list", func(ctx *gin.Context) {
			type ReqJson = vo.ListPersonReq
			var req ReqJson
			if err := ctx.BindJSON(&req); err != nil {
				return
			}
			logicRsp, err := s.personLogic.ListPerson(ctx, req)
			handleBizVoRsp(ctx, logicRsp, err)
		})
	}

	// 通用 人员管理接口
	supermarketDirectorApiGroup := api.Group("/supermarket_director")
	{
		supermarketDirectorApiGroup.POST("/create", func(ctx *gin.Context) {
			type ReqJson = vo.CreateSupermarketDirectorReq
			var req ReqJson
			if err := ctx.BindJSON(&req); err != nil {
				return
			}

			logicRsp, err := s.supermarketDirectorLogic.CreateSupermarketDirector(ctx, req)
			handleBizRsp(ctx, logicRsp, err)
		})
		// update
		supermarketDirectorApiGroup.POST("/update", func(ctx *gin.Context) {
			var req vo.UpdateSupermarketDirectorReq
			if err := ctx.BindJSON(&req); err != nil {
				return
			}
			_, err := s.supermarketDirectorLogic.Update(ctx, &vo.UpdateSupermarketDirectorReq{
				ID:             req.ID,
				DirectorID:     req.DirectorID,
				SupermarketID:  req.SupermarketID,
				DirectorPoints: req.DirectorPoints,
				Note:           req.Note,
			})
			handleBizRsp(ctx, nil, err)
		})
		// list
		supermarketDirectorApiGroup.POST("/list", func(ctx *gin.Context) {
			type ReqJson = vo.ListSupermarketDirectorReq
			var req ReqJson
			if err := ctx.BindJSON(&req); err != nil {
				return
			}
			logicRsp, err := s.supermarketDirectorLogic.ListSupermarketDirector(ctx, req)
			handleBizVoRsp(ctx, logicRsp, err)
		})

		// delete
		supermarketDirectorApiGroup.POST("/delete", func(ctx *gin.Context) {
			type ReqJson = vo.ListPersonReq
			var req ReqJson
			if err := ctx.BindJSON(&req); err != nil {
				return
			}
			logicRsp, err := s.personLogic.ListPerson(ctx, req)
			handleBizVoRsp(ctx, logicRsp, err)
		})
	}
	return nil
}

type ServiceHandleFunc func(svcReq any) (svcRsp any, err error)
type RepoHandleFunc func(repoReq any) (repoRsp any, err error)

func handleServiceRsp(ctx *gin.Context, svcReq any, handle ServiceHandleFunc) {
	if err := ctx.BindJSON(svcReq); err != nil {
		return
	}

	svcRsp, err := handle(svcReq)

	handleBizRsp(ctx, svcRsp, err)
}

func handleBizRsp(ctx *gin.Context, data any, err error) {
	if err != nil {
		ctx.JSON(200, RspModel{
			Code: 1, // todo 错误码细化
			Msg:  err.Error(),
			Data: data,
		})
		return
	}
	ctx.JSON(200, RspModel{
		Code: 0,
		Msg:  "success",
		Data: data,
	})
}

// 专门处理列表类的接口
func handleBizListRsp(ctx *gin.Context, data any, total int64, err error) {
	handleBizRsp(ctx, map[string]any{"List": data, "Total": total}, err)
}

func handleBizVoRsp(ctx *gin.Context, vo any, err error) {
	handleBizRsp(ctx, vo, err)
}
